package cn.dagteam.springboot.mongodb.starter.tools;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 各种转换的集合
 *
 * @author gaofeng
 */
public class Converts {

    private static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 转成字符串，日期类型格式化为yyyy-MM-dd HH:mm:ss
     */
    public static String toString(Object obj) {
        if (obj == null) {
            return "";
        }
        if (obj instanceof Date) {
            SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);
            return sdf.format((Date) obj);
        } else if (obj instanceof Enum) {
            try {
                Method getValueMethod = ((Enum<?>) obj).getClass().getDeclaredMethod("getValue");
                return toString(getValueMethod.invoke(obj));
            } catch (NoSuchMethodException e) {
                return ((Enum<?>) obj).name();
            } catch (Exception e) {
                return "";
            }
        }
        return obj.toString();
    }

    /**
     * 转成int，取数值
     */
    public static int toInt(Object obj) {
        if (obj == null) {
            return 0;
        }
        return Double.valueOf(toString(obj)).intValue();
    }

    /**
     * 转成Integer
     */
    public static Integer toInteger(Object obj) {
        if (obj == null) {
            return null;
        }
        return Double.valueOf(toString(obj)).intValue();
    }

    /**
     * 转成long
     */
    public static long toLongValue(Object obj) {
        if (obj == null) {
            return 0l;
        }
        return Double.valueOf(toString(obj)).longValue();
    }

    /**
     * 转成Long
     */
    public static Long toLong(Object obj) {
        if (obj == null) {
            return null;
        }
        return Double.valueOf(toString(obj)).longValue();
    }

    /**
     * 转成double
     */
    public static double toDoubleValue(Object obj) {
        if (obj == null) {
            return 0.0;
        }
        return Double.parseDouble(toString(obj));
    }

    /**
     * 转成Double
     */
    public static Double toDouble(Object obj) {
        if (obj == null) {
            return null;
        }
        return Double.valueOf(toString(obj));
    }

    /**
     * 转成float
     */
    public static float toFloatValue(Object obj) {
        if (obj == null) {
            return (float) 0.0;
        }
        return Double.valueOf(toString(obj)).floatValue();
    }

    /**
     * 转成Float
     */
    public static Float toFloat(Object obj) {
        if (obj == null) {
            return null;
        }
        return Float.valueOf(toString(obj));
    }

    /**
     * 转成日期类型，只要满足一种格式就能转换
     */
    public static Date toDate(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Date) {
            return (Date) obj;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);
            return sdf.parse(toString(obj));
        } catch (ParseException e) {
            // 转换失败，说明不符合系统要求的格式，具体格式参考DatePattern
            return null;
        }
    }

    /**
     * 转成boolean
     */
    public static boolean toBoolean(Object obj) {
        if (obj == null) {
            return false;
        }
        return Boolean.parseBoolean(toString(obj));
    }

    public static Boolean toBooleanObject(Object obj) {
        return toBoolean(obj) ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 根据给出的类型进行转换，只支持基本类型，其他类型直接原值返回
     */
    @SuppressWarnings("unchecked")
    public static <T> T toByClass(Object obj, Class<T> clazz) {
        if (String.class == clazz) {
            return (T) toString(obj);
        } else if (Double.class == clazz || double.class == clazz) {
            return (T) toDouble(obj);
        } else if (Integer.class == clazz || int.class == clazz) {
            return (T) toInteger(obj);
        } else if (Float.class == clazz || float.class == clazz) {
            return (T) toFloat(obj);
        } else if (Date.class == clazz) {
            return (T) toDate(obj);
        } else if (Long.class == clazz || long.class == clazz) {
            return (T) toLong(obj);
        } else if (Boolean.class == clazz || boolean.class == clazz) {
            return (T) toBooleanObject(obj);
        } else if (Enum.class.isAssignableFrom(clazz)) {
            if (obj == null) {
                return null;
            }
            @SuppressWarnings("rawtypes")
            Class<? extends Enum> enumClass = (Class<? extends Enum>) clazz;
            return (T) Enum.valueOf(enumClass, String.valueOf(obj));
        } else {
            return (T) obj;
        }
    }

    public static <T> T[] toArrayByClass(Object[] source, Class<T> clazz) {
        if (source != null && source.length > 0) {
            @SuppressWarnings("unchecked")
            T[] t = (T[]) Array.newInstance(clazz, source.length);
            for (int i = 0; i < source.length; i++) {
                t[i] = toByClass(source[i], clazz);
            }
            return t;
        }
        return null;
    }
}